2 Created on May 17, 2010
4 @author: Sergio Martins
8 pygtk.require20() #require pygtk version 2.0
14 sys.path.append('/usr/local/samba/lib/python2.7/site-packages/')
23 from sambagtk.dialogs import AboutDialog
24 from sambagtk.sam import SAMConnectDialog
25 from sambagtk.pysrvsvc import srvsvcConnectDialog
28 class SambaUtilities(object):
30 def __init__(self, connection_args={}, additional_connection_arguments={}):
34 # these are the old windows of the utilities. We reparent the main
35 # widget so these arn't displayed but we need the handle so we can
36 # call functions and grab objects
37 self.sam_window = None
38 self.regedit_window = None
39 self.svcctl_window = None
40 self.crontab_window = None
41 self.srvsvc_window = None
42 self.srvsvc_init= False
44 self.connection_args = connection_args
45 self.additional_connection_args = {} #arguments not supported by all utilities, such as domain_index
46 self.additional_connection_args.update({"info_callback":self.server_info_callback}) #to save info or get updated info
47 self.print_redirect_sring = ""
49 self.update_sensitivity()
51 self.push_status_message("Utility started successfully.")
52 self.utilites_notebook.grab_focus() #So switching to the regedit tab doesn't automatically focus the keys tree view
54 if (connection_args.has_key("connect_now") and connection_args["connect_now"]):
55 self.on_connect_all_button_clicked(None)
59 # get a builder and put it to work
60 builder = gtk.Builder()
61 builder.add_from_file("main.glade")
63 # dictionary for connections
64 connections = {"on_main_window_destroy": gtk.main_quit,
65 "on_main_window_key_press_event": self.on_main_window_key_press_event,
67 "on_connect_all_item_activate": self.on_connect_all_button_clicked,
68 "on_disconnect_all_item_activate": self.on_disconnect_all_button_clicked,
69 "on_quit_item_activate": self.on_quit_item_activate,
70 "on_clear_log_activate": self.on_clear_log_activate,
71 "on_connection_info_item_activate": self.on_connection_info_item_activate,
72 "on_about_item_activate": self.on_about_item_activate,
74 "on_connect_all_button_clicked": self.on_connect_all_button_clicked,
75 "on_disconnect_all_button_clicked": self.on_disconnect_all_button_clicked,
76 "on_clear_log_button_clicked": self.on_clear_log_activate,
78 "on_utility_notebook_switch_page": self.on_utility_notebook_switch_page,
82 builder.connect_signals(connections)
85 self.window = builder.get_object("main_window")
86 self.menubar_viewport = builder.get_object("menubar_viewport")
87 self.menubar = builder.get_object("menubar")
88 self.connect_all_item = builder.get_object("connect_all_item")
89 self.disconnect_all_item = builder.get_object("disconnect_all_item")
91 self.toolbar_viewport = builder.get_object("toolbar_viewport")
92 self.toolbar = builder.get_object("toolbar")
93 self.connect_all_button = builder.get_object("connect_all_button")
94 self.disconnect_all_button = builder.get_object("disconnect_all_button")
96 self.utilites_notebook = builder.get_object("utility_notebook")
98 self.server_label = builder.get_object("server_label")
99 self.username_label = builder.get_object("username_label")
100 self.status_label = builder.get_object("status_label")
101 self.messages_textview = builder.get_object("messages_textview")
103 self.sam_viewport = builder.get_object("sam_viewport")
104 self.svcctl_viewport = builder.get_object("svcctl_viewport")
105 self.crontab_viewport = builder.get_object("crontab_viewport")
106 self.regedit_viewport = builder.get_object("regedit_viewport")
107 self.srvsvc_viewport = builder.get_object("srvsvc_viewport")
109 self.progressbar = builder.get_object("progressbar")
110 self.statusbar = builder.get_object("statusbar")
113 def init_sam_page(self):
115 args = self.connection_args.copy()
116 if self.additional_connection_args.has_key("domain_index"):
117 args.update({"domain_index":self.additional_connection_args["domain_index"]})
118 if self.additional_connection_args.has_key("info_callback"):
119 args.update({"info_callback":self.additional_connection_args["info_callback"]})
121 self.sam_window = pygwsam.SAMWindow(**args) #start up the utility
122 self.sam_window.users_groups_notebook.reparent(self.sam_viewport) #reparent the main widget into a notebook tab
123 self.sam_viewport.show_all() #unhide all widgets
125 #We'll be displaying this later. We need to unparent it before attaching it to another container
126 self.sam_window.menubar.unparent()
127 self.sam_window.toolbar.unparent()
128 self.sam_window.statusbar = self.statusbar #we simply tell the utility to use our status bar instead
130 self.set_status("User tab initialized.")
131 self.update_sensitivity()
133 def init_srvsvc_page(self):
135 args = self.connection_args.copy()
136 if self.additional_connection_args.has_key("info_callback"):
137 args.update({"info_callback":self.additional_connection_args["info_callback"]})
139 self.srvsvc_window = pygwshare.ShareWindow(**args) #start up the utility
140 self.srvsvc_window.share_notebook.reparent(self.srvsvc_viewport) #reparent the main widget into a notebook tab
141 self.srvsvc_viewport.show_all() #unhide all widgets
143 #We'll be displaying this later. We need to unparent it before attaching it to another container
145 self.srvsvc_window.toolbar.unparent()
146 self.srvsvc_window.statusbar = self.statusbar #we simply tell the utility to use our status bar instead
148 self.set_status("Share Manager tab initialized.")
149 self.update_sensitivity()
151 def init_regedit_page(self):
152 args = self.connection_args.copy()
153 if self.additional_connection_args.has_key("info_callback"):
154 args.update({"info_callback":self.additional_connection_args["info_callback"]})
155 self.regedit_window = pygwregedit.RegEditWindow(**args) #start up the utility
156 self.regedit_window.hpaned.reparent(self.regedit_viewport) #reparent the main widget into a notebook tab
157 self.regedit_viewport.show_all() #unhide all widgets
159 self.regedit_window.menubar.unparent()
160 self.regedit_window.toolbar.unparent()
161 self.regedit_window.progressbar = self.progressbar
162 self.regedit_window.statusbar = self.statusbar
164 self.set_status("Regedit tab initialized.")
165 self.update_sensitivity()
167 def init_svcctl_page(self):
168 args = self.connection_args.copy()
169 if self.additional_connection_args.has_key("info_callback"):
170 args.update({"info_callback":self.additional_connection_args["info_callback"]})
171 self.svcctl_window = pygwsvcctl.SvcCtlWindow(**args) #start up the utility
172 self.svcctl_window.scrolledwindow.reparent(self.svcctl_viewport) #reparent the main widget into a notebook tab
173 self.svcctl_viewport.show_all() #unhide all widgets
175 self.svcctl_window.menubar.unparent()
176 self.svcctl_window.toolbar.unparent()
177 self.svcctl_window.progressbar = self.progressbar
178 self.svcctl_window.statusbar = self.statusbar
180 self.set_status("Services tab initialized.")
181 self.update_sensitivity()
183 def init_crontab_page(self):
184 args = self.connection_args.copy()
185 if self.additional_connection_args.has_key("info_callback"):
186 args.update({"info_callback":self.additional_connection_args["info_callback"]})
187 self.crontab_window = pygwcrontab.CronTabWindow(**args) #start up the utility
188 self.crontab_window.scrolledwindow.reparent(self.crontab_viewport) #reparent the main widget into a notebook tab
189 self.crontab_viewport.show_all() #unhide all widgets
191 self.crontab_window.menubar.unparent()
192 self.crontab_window.toolbar.unparent()
193 self.crontab_window.statusbar = self.statusbar
195 self.set_status("Scheduled tasks tab initialized.")
196 self.update_sensitivity()
198 def sam_initialized(self):
199 return self.sam_window is not None
201 def regedit_initialized(self):
202 return self.regedit_window is not None
204 def srvsvc_initialized (self):
205 return self.srvsvc_window is not None
207 def svcctl_initialized(self):
208 return self.svcctl_window is not None
210 def crontab_initialized(self):
211 return self.crontab_window is not None
213 def update_sensitivity(self):
214 sam_connected = self.sam_initialized() and self.sam_window.connected()
215 srvsvc_connected = self.srvsvc_initialized() and self.srvsvc_window.connected()
216 regedit_connected = self.regedit_initialized() and self.regedit_window.connected()
217 svcctl_connected = self.svcctl_initialized() and self.svcctl_window.connected()
218 crontab_connected = self.crontab_initialized() and self.crontab_window.connected()
219 all_connected = sam_connected and regedit_connected and svcctl_connected and crontab_connected and srvsvc_connected
220 all_disconnected = (not sam_connected) and (not regedit_connected) and (not svcctl_connected) and (not crontab_connected) and (not srvsvc_connected)
222 self.connect_all_button.set_sensitive(not all_connected)
223 self.disconnect_all_button.set_sensitive(not all_disconnected)
224 self.connect_all_item.set_sensitive(not all_connected)
225 self.disconnect_all_item.set_sensitive(not all_disconnected)
227 self.server_label.set_text(self.connection_args.has_key("server") and self.connection_args["server"] or "Unknown")
228 self.username_label.set_text(self.connection_args.has_key("username") and self.connection_args["username"] or "Unknwon")
230 self.status_label.set_text("All connected")
231 elif (all_disconnected):
232 self.status_label.set_text("All disconnected")
234 connected_utilities = []
236 connected_utilities.append("User Manager")
238 connected_utilities.append("Share Manager")
239 if regedit_connected:
240 connected_utilities.append("Registry Editor")
242 connected_utilities.append("Services Manager")
243 if crontab_connected:
244 connected_utilities.append("Task Scheduler")
245 if len(connected_utilities) > 1:
246 connected_utilities[-1] = "and %s" % connected_utilities[-1]
247 self.status_label.set_text("%s %s" % (", ".join(connected_utilities), "connected."))
249 def server_info_callback(self, server = "", username = "", transport_type = None):
251 self.connection_args.update({"server":server})
253 self.connection_args.update({"username":username})
255 self.connection_args.update({"transport_type":transport_type})
257 def run_message_dialog(self, type, buttons, message, parent = None):
261 message_box = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, type, buttons, message)
262 response = message_box.run()
267 def run_connect_all_dialog(self):
268 """Runs the connection dialog and saves connection arguments to self.connection_args
270 returns True if arguments were uptained successfully"""
271 #TODO in this function: handle domain selection
273 #args and their default values
274 important_args = {"server":"", "username":"", "transport_type":0, }
275 for item in important_args.keys():
276 args.update(self.connection_args.has_key(item) and {item:self.connection_args[item]} or {item:important_args[item]})
278 dialog = SAMConnectDialog(**args)
281 # loop to handle the failures
283 response_id = dialog.run()
285 if (response_id != gtk.RESPONSE_OK):
289 server = dialog.get_server_address()
290 username = dialog.get_username()
291 if server != "" and username != "":
292 self.connection_args.update({"server":server})
293 self.connection_args.update({"username":username})
294 self.connection_args.update({"transport_type":dialog.get_transport_type()})
295 self.connection_args.update({"password":dialog.get_password()})
296 self.connection_args.update({"connect_now":True})
297 self.additional_connection_args.update({"domain_index":0}) #TODO: get domain index
300 self.run_message_dialog(gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "You must enter a server address and username.")
306 def write(self, string): #Make this class a writeable object. Used so we can redirect print statements
308 self.push_status_message(self.print_redirect_sring)
309 print >>sys.__stdout__, self.print_redirect_sring #also print the string normally
310 self.print_redirect_sring = ""
312 self.print_redirect_sring += string
314 def push_status_message(self, message):
315 """Pushes a message to the status textview in the main tab. This function inserts a \"\\n\" for you."""
316 buffer = self.messages_textview.get_buffer()
317 text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
318 text += message + "\n"
319 buffer.set_text(text)
321 #scroll to the bottom
322 self.messages_textview.scroll_to_iter(buffer.get_end_iter(), 0.0)
324 def set_status(self, message):
325 self.statusbar.pop(0)
326 self.statusbar.push(0, message)
327 self.push_status_message(message)
329 def on_main_window_key_press_event(self, widget, event):
330 current_page = self.utilites_notebook.get_current_page()
332 if current_page == 1:
333 self.sam_window.on_key_press(widget, event)
334 elif current_page == 2:
335 self.srvsvc_window.on_key_press(widget, event)
336 elif current_page == 3:
337 self.regedit_window.on_key_press(widget, event)
338 elif current_page == 4:
339 self.svcctl_window.on_key_press(widget, event)
340 elif current_page == 5:
341 self.crontab_window.on_key_press(widget, event)
343 def on_utility_notebook_switch_page(self, widget, page, page_num):
344 if page_num == 0: #main page
347 children = self.menubar_viewport.get_children()
348 self.menubar_viewport.remove(children[0])
349 self.menubar_viewport.add(self.menubar)
350 self.menubar_viewport.show_all()
352 children = self.toolbar_viewport.get_children()
353 self.toolbar_viewport.remove(children[0])
354 self.toolbar_viewport.add(self.toolbar)
355 self.toolbar_viewport.show_all()
357 self.update_sensitivity()
359 elif page_num == 1: #Sam page
360 if self.sam_viewport.child == None:
364 children = self.menubar_viewport.get_children()
365 self.menubar_viewport.remove(children[0])
366 self.menubar_viewport.add(self.sam_window.menubar)
367 self.menubar_viewport.show_all()
370 children = self.toolbar_viewport.get_children()
371 self.toolbar_viewport.remove(children[0])
372 self.toolbar_viewport.add(self.sam_window.toolbar)
373 self.toolbar_viewport.show_all()
376 elif page_num == 2: #Share page
377 if self.srvsvc_viewport.child == None:
378 self.init_srvsvc_page()
381 children = self.menubar_viewport.get_children()
382 self.menubar_viewport.remove(children[0])
383 if self.srvsvc_init is False:
384 self.srvsvc_window.menubar.reparent(self.menubar_viewport)
385 self.srvsvc_init = True
387 self.menubar_viewport.add(self.srvsvc_window.menubar)
388 self.menubar_viewport.show_all()
391 children = self.toolbar_viewport.get_children()
392 self.toolbar_viewport.remove(children[0])
393 self.srvsvc_window.toolbar.unparent()
394 self.toolbar_viewport.add(self.srvsvc_window.toolbar)
395 self.toolbar_viewport.show_all()
397 self.srvsvc_window.hide()
399 elif page_num == 3: #Regedit page
400 if self.regedit_viewport.child == None:
401 self.init_regedit_page()
404 children = self.menubar_viewport.get_children()
405 self.menubar_viewport.remove(children[0])
406 self.menubar_viewport.add(self.regedit_window.menubar)
407 self.menubar_viewport.show_all()
410 children = self.toolbar_viewport.get_children()
411 self.toolbar_viewport.remove(children[0])
412 self.toolbar_viewport.add(self.regedit_window.toolbar)
413 self.toolbar_viewport.show_all()
415 elif page_num == 4: #Services page
416 if self.svcctl_viewport.child == None:
417 self.init_svcctl_page()
420 children = self.menubar_viewport.get_children()
421 self.menubar_viewport.remove(children[0])
422 self.menubar_viewport.add(self.svcctl_window.menubar)
423 self.menubar_viewport.show_all()
426 children = self.toolbar_viewport.get_children()
427 self.toolbar_viewport.remove(children[0])
428 self.toolbar_viewport.add(self.svcctl_window.toolbar)
429 self.toolbar_viewport.show_all()
431 elif page_num == 5: #Crontab page
432 if self.crontab_viewport.child == None:
433 self.init_crontab_page()
436 children = self.menubar_viewport.get_children()
437 self.menubar_viewport.remove(children[0])
438 self.menubar_viewport.add(self.crontab_window.menubar)
439 self.menubar_viewport.show_all()
442 children = self.toolbar_viewport.get_children()
443 self.toolbar_viewport.remove(children[0])
444 self.toolbar_viewport.add(self.crontab_window.toolbar)
445 self.toolbar_viewport.show_all()
447 def on_connect_all_button_clicked(self, widget):
449 if self.connection_args.has_key("connect_now") and self.connection_args["connect_now"]:
450 #if the user specified --connect-now then we probably have enough arguments to connect
452 if self.sam_initialized():
453 if not self.sam_window.connected():
454 self.sam_window.on_connect_item_activate(None, **self.connection_args)
458 if self.srvsvc_initialized():
459 if not self.srvsvc_window.connected():
460 self.srvsvc_window.on_connect_item_activate(None, **self.connection_args)
462 self.init_srvsvc_page()
464 if self.regedit_initialized():
465 if not self.regedit_window.connected():
466 self.regedit_window.on_connect_item_activate(None, **self.connection_args)
468 self.init_regedit_page()
470 if self.svcctl_initialized():
471 if not self.svcctl_window.connected():
472 self.svcctl_window.on_connect_item_activate(None, **self.connection_args)
474 self.init_svcctl_page()
476 if self.crontab_initialized():
477 if not self.crontab_window.connected():
478 self.crontab_window.on_connect_item_activate(None, **self.connection_args)
480 self.init_crontab_page()
483 if self.run_connect_all_dialog():
484 self.on_connect_all_button_clicked(None)
486 def on_disconnect_all_button_clicked(self, widget):
487 if self.sam_initialized():
488 self.sam_window.on_disconnect_item_activate(None)
489 if self.srvsvc_initialized():
490 self.srvsvc_window.on_disconnect_item_activate(None)
491 if self.regedit_initialized():
492 self.regedit_window.on_disconnect_item_activate(None)
493 if self.svcctl_initialized():
494 self.svcctl_window.on_disconnect_item_activate(None)
495 if self.crontab_initialized():
496 self.crontab_window.on_disconnect_item_activate(None)
497 self.update_sensitivity()
499 def on_connection_info_item_activate(self, widget):
500 #TODO: display connection info (via a dialog or custom window?)
501 self.push_status_message("This is not implemented yet!")
504 def on_clear_log_activate(self, widget):
505 self.messages_textview.get_buffer().set_text("")
508 def on_about_item_activate(self, widget):
509 dialog = AboutDialog(
511 "A tool to display other utilities in a simple, unified window.",
518 def on_quit_item_activate(self, widget):
521 #************ END OF CLASS ***************
524 print "Usage: %s [OPTIONS]" % (str(os.path.split(__file__)[-1]))
525 print "All options are optional. The user will be queried for additional information if needed.\n"
526 print " -s --server\t\tspecify the server to connect to."
527 print " -u --user\t\tspecify the user."
528 print " -p --password\tThe password for the user."
529 print " -t --transport\tTransport type.\n\t\t\t\t0 for RPC, SMB, TCP/IP\n\t\t\t\t1 for RPC, TCP/IP\n\t\t\t\t2 for localhost."
530 print " -c --connect-now\tSkip the connect dialog."
535 try: #get arguments into a nicer format
536 opts, args = getopt.getopt(argv, "chu:s:p:t:", ["help", "user=", "server=", "password=", "connect-now", "transport="])
537 except getopt.GetoptError:
541 for opt, arg in opts:
542 if opt in ("-h", "--help"):
545 elif opt in ("-s", "--server"):
546 arguments.update({"server":arg})
547 elif opt in ("-u", "--user"):
548 arguments.update({"username":arg})
549 elif opt in ("-p", "--password"):
550 arguments.update({"password":arg})
551 elif opt in ("-t", "--transport"):
552 arguments.update({"transport_type":int(arg)})
553 elif opt in ("-c", "--connect-now"):
554 arguments.update({"connect_now":True})
558 if __name__ == "__main__":
559 arguments = ParseArgs(sys.argv[1:])
560 gtk.gdk.threads_init()
561 main_window = SambaUtilities(arguments)
562 sys.stdout = main_window #redirect print statements to the write() function of this class