remove sys append by default, add gpl
[samba-gtk.git] / sambagtk / main.py
1 '''
2 Created on May 17, 2010
3
4 @author: Sergio Martins
5 '''
6 import sys
7 import pygtk
8 pygtk.require20() #require pygtk version 2.0
9 import gtk
10 import gtk.glade
11 import os.path
12 import getopt
13
14 #sys.path.append('/usr/local/samba/lib/python2.7/site-packages/')
15 # for use against the default binaries from default .configure.developer for use on python 2.7
16 # Uncomment the above line if it is yor your config , else edit it as required
17
18
19 import pygwsam
20 import pygwregedit
21 import pygwcrontab
22 import pygwsvcctl
23 import pygwshare
24
25 from sambagtk.dialogs import AboutDialog
26 from sambagtk.sam import SAMConnectDialog
27 from sambagtk.pysrvsvc import srvsvcConnectDialog
28
29
30 class SambaUtilities(object):
31
32     def __init__(self, connection_args={}, additional_connection_arguments={}):
33
34         self.create()
35
36         # these are the old windows of the utilities. We reparent the main
37         # widget so these arn't displayed but we need the handle so we can
38         # call functions and grab objects
39         self.sam_window = None
40         self.regedit_window = None
41         self.svcctl_window = None
42         self.crontab_window = None
43         self.srvsvc_window = None
44         self.srvsvc_init= False
45
46         self.connection_args = connection_args
47         self.additional_connection_args = {} #arguments not supported by all utilities, such as domain_index
48         self.additional_connection_args.update({"info_callback":self.server_info_callback}) #to save info or get updated info
49         self.print_redirect_sring = ""
50
51         self.update_sensitivity()
52         self.window.show()
53         self.push_status_message("Utility started successfully.")
54         self.utilites_notebook.grab_focus() #So switching to the regedit tab doesn't automatically focus the keys tree view
55
56         if (connection_args.has_key("connect_now") and connection_args["connect_now"]):
57             self.on_connect_all_button_clicked(None)
58
59
60     def create(self):
61         # get a builder and put it to work
62         builder = gtk.Builder()
63         builder.add_from_file("main.glade")
64
65         # dictionary for connections
66         connections = {"on_main_window_destroy": gtk.main_quit,
67                        "on_main_window_key_press_event": self.on_main_window_key_press_event,
68
69                        "on_connect_all_item_activate": self.on_connect_all_button_clicked,
70                        "on_disconnect_all_item_activate": self.on_disconnect_all_button_clicked,
71                        "on_quit_item_activate": self.on_quit_item_activate,
72                        "on_clear_log_activate": self.on_clear_log_activate,
73                        "on_connection_info_item_activate": self.on_connection_info_item_activate,
74                        "on_about_item_activate": self.on_about_item_activate,
75
76                        "on_connect_all_button_clicked": self.on_connect_all_button_clicked,
77                        "on_disconnect_all_button_clicked": self.on_disconnect_all_button_clicked,
78                        "on_clear_log_button_clicked": self.on_clear_log_activate,
79
80                        "on_utility_notebook_switch_page": self.on_utility_notebook_switch_page,
81
82                        }
83         #Make the connections
84         builder.connect_signals(connections)
85
86         #Handles
87         self.window = builder.get_object("main_window")
88         self.menubar_viewport = builder.get_object("menubar_viewport")
89         self.menubar = builder.get_object("menubar")
90         self.connect_all_item = builder.get_object("connect_all_item")
91         self.disconnect_all_item = builder.get_object("disconnect_all_item")
92
93         self.toolbar_viewport = builder.get_object("toolbar_viewport")
94         self.toolbar = builder.get_object("toolbar")
95         self.connect_all_button = builder.get_object("connect_all_button")
96         self.disconnect_all_button = builder.get_object("disconnect_all_button")
97
98         self.utilites_notebook = builder.get_object("utility_notebook")
99
100         self.server_label = builder.get_object("server_label")
101         self.username_label = builder.get_object("username_label")
102         self.status_label = builder.get_object("status_label")
103         self.messages_textview = builder.get_object("messages_textview")
104
105         self.sam_viewport = builder.get_object("sam_viewport")
106         self.svcctl_viewport = builder.get_object("svcctl_viewport")
107         self.crontab_viewport = builder.get_object("crontab_viewport")
108         self.regedit_viewport = builder.get_object("regedit_viewport")
109         self.srvsvc_viewport = builder.get_object("srvsvc_viewport")
110
111         self.progressbar = builder.get_object("progressbar")
112         self.statusbar = builder.get_object("statusbar")
113
114
115     def init_sam_page(self):
116
117         args = self.connection_args.copy()
118         if self.additional_connection_args.has_key("domain_index"):
119             args.update({"domain_index":self.additional_connection_args["domain_index"]})
120         if self.additional_connection_args.has_key("info_callback"):
121             args.update({"info_callback":self.additional_connection_args["info_callback"]})
122
123         self.sam_window = pygwsam.SAMWindow(**args) #start up the utility
124         self.sam_window.users_groups_notebook.reparent(self.sam_viewport) #reparent the main widget into a notebook tab
125         self.sam_viewport.show_all() #unhide all widgets
126
127         #We'll be displaying this later. We need to unparent it before attaching it to another container
128         self.sam_window.menubar.unparent()
129         self.sam_window.toolbar.unparent()
130         self.sam_window.statusbar = self.statusbar #we simply tell the utility to use our status bar instead
131
132         self.set_status("User tab initialized.")
133         self.update_sensitivity()
134
135     def init_srvsvc_page(self):
136
137         args = self.connection_args.copy()
138         if self.additional_connection_args.has_key("info_callback"):
139             args.update({"info_callback":self.additional_connection_args["info_callback"]})
140
141         self.srvsvc_window = pygwshare.ShareWindow(**args) #start up the utility
142         self.srvsvc_window.share_notebook.reparent(self.srvsvc_viewport) #reparent the main widget into a notebook tab
143         self.srvsvc_viewport.show_all() #unhide all widgets
144
145         #We'll be displaying this later. We need to unparent it before attaching it to another container
146
147         self.srvsvc_window.toolbar.unparent()
148         self.srvsvc_window.statusbar = self.statusbar #we simply tell the utility to use our status bar instead
149
150         self.set_status("Share Manager tab initialized.")
151         self.update_sensitivity()
152
153     def init_regedit_page(self):
154         args = self.connection_args.copy()
155         if self.additional_connection_args.has_key("info_callback"):
156             args.update({"info_callback":self.additional_connection_args["info_callback"]})
157         self.regedit_window = pygwregedit.RegEditWindow(**args) #start up the utility
158         self.regedit_window.hpaned.reparent(self.regedit_viewport) #reparent the main widget into a notebook tab
159         self.regedit_viewport.show_all() #unhide all widgets
160
161         self.regedit_window.menubar.unparent()
162         self.regedit_window.toolbar.unparent()
163         self.regedit_window.progressbar = self.progressbar
164         self.regedit_window.statusbar = self.statusbar
165
166         self.set_status("Regedit tab initialized.")
167         self.update_sensitivity()
168
169     def init_svcctl_page(self):
170         args = self.connection_args.copy()
171         if self.additional_connection_args.has_key("info_callback"):
172             args.update({"info_callback":self.additional_connection_args["info_callback"]})
173         self.svcctl_window = pygwsvcctl.SvcCtlWindow(**args) #start up the utility
174         self.svcctl_window.scrolledwindow.reparent(self.svcctl_viewport) #reparent the main widget into a notebook tab
175         self.svcctl_viewport.show_all() #unhide all widgets
176
177         self.svcctl_window.menubar.unparent()
178         self.svcctl_window.toolbar.unparent()
179         self.svcctl_window.progressbar = self.progressbar
180         self.svcctl_window.statusbar = self.statusbar
181
182         self.set_status("Services tab initialized.")
183         self.update_sensitivity()
184
185     def init_crontab_page(self):
186         args = self.connection_args.copy()
187         if self.additional_connection_args.has_key("info_callback"):
188             args.update({"info_callback":self.additional_connection_args["info_callback"]})
189         self.crontab_window = pygwcrontab.CronTabWindow(**args) #start up the utility
190         self.crontab_window.scrolledwindow.reparent(self.crontab_viewport) #reparent the main widget into a notebook tab
191         self.crontab_viewport.show_all() #unhide all widgets
192
193         self.crontab_window.menubar.unparent()
194         self.crontab_window.toolbar.unparent()
195         self.crontab_window.statusbar = self.statusbar
196
197         self.set_status("Scheduled tasks tab initialized.")
198         self.update_sensitivity()
199
200     def sam_initialized(self):
201         return self.sam_window is not None
202
203     def regedit_initialized(self):
204         return self.regedit_window is not None
205
206     def srvsvc_initialized (self):
207         return self.srvsvc_window is not None
208
209     def svcctl_initialized(self):
210         return self.svcctl_window is not None
211
212     def crontab_initialized(self):
213         return self.crontab_window is not None
214
215     def update_sensitivity(self):
216         sam_connected = self.sam_initialized() and self.sam_window.connected()
217         srvsvc_connected = self.srvsvc_initialized() and self.srvsvc_window.connected()
218         regedit_connected = self.regedit_initialized() and self.regedit_window.connected()
219         svcctl_connected = self.svcctl_initialized() and self.svcctl_window.connected()
220         crontab_connected = self.crontab_initialized() and self.crontab_window.connected()
221         all_connected = sam_connected and regedit_connected and svcctl_connected and crontab_connected and srvsvc_connected
222         all_disconnected = (not sam_connected) and (not regedit_connected) and (not svcctl_connected) and (not crontab_connected) and (not srvsvc_connected)
223
224         self.connect_all_button.set_sensitive(not all_connected)
225         self.disconnect_all_button.set_sensitive(not all_disconnected)
226         self.connect_all_item.set_sensitive(not all_connected)
227         self.disconnect_all_item.set_sensitive(not all_disconnected)
228
229         self.server_label.set_text(self.connection_args.has_key("server") and self.connection_args["server"] or "Unknown")
230         self.username_label.set_text(self.connection_args.has_key("username") and self.connection_args["username"] or "Unknwon")
231         if (all_connected):
232             self.status_label.set_text("All connected")
233         elif (all_disconnected):
234             self.status_label.set_text("All disconnected")
235         else:
236             connected_utilities = []
237             if sam_connected:
238                 connected_utilities.append("User Manager")
239             if srvsvc_connected:
240                 connected_utilities.append("Share Manager")
241             if regedit_connected:
242                 connected_utilities.append("Registry Editor")
243             if svcctl_connected:
244                 connected_utilities.append("Services Manager")
245             if crontab_connected:
246                 connected_utilities.append("Task Scheduler")
247             if len(connected_utilities) > 1:
248                 connected_utilities[-1] = "and %s" % connected_utilities[-1]
249             self.status_label.set_text("%s %s" % (", ".join(connected_utilities), "connected."))
250
251     def server_info_callback(self, server = "", username = "", transport_type = None):
252         if server:
253             self.connection_args.update({"server":server})
254         if username:
255             self.connection_args.update({"username":username})
256         if transport_type:
257             self.connection_args.update({"transport_type":transport_type})
258
259     def run_message_dialog(self, type, buttons, message, parent = None):
260         if (parent == None):
261             parent = self.window
262
263         message_box = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, type, buttons, message)
264         response = message_box.run()
265         message_box.hide()
266
267         return response
268
269     def run_connect_all_dialog(self):
270         """Runs the connection dialog and saves connection arguments to self.connection_args
271
272         returns True if arguments were uptained successfully"""
273         #TODO in this function: handle domain selection
274         args = {}
275         #args and their default values
276         important_args = {"server":"", "username":"", "transport_type":0, }
277         for item in important_args.keys():
278                 args.update(self.connection_args.has_key(item) and {item:self.connection_args[item]} or {item:important_args[item]})
279
280         dialog = SAMConnectDialog(**args)
281         dialog.show_all()
282
283         # loop to handle the failures
284         while True:
285             response_id = dialog.run()
286
287             if (response_id != gtk.RESPONSE_OK):
288                 dialog.hide()
289                 return False
290             else:
291                 server = dialog.get_server_address()
292                 username = dialog.get_username()
293                 if server != "" and username != "":
294                     self.connection_args.update({"server":server})
295                     self.connection_args.update({"username":username})
296                     self.connection_args.update({"transport_type":dialog.get_transport_type()})
297                     self.connection_args.update({"password":dialog.get_password()})
298                     self.connection_args.update({"connect_now":True})
299                     self.additional_connection_args.update({"domain_index":0}) #TODO: get domain index
300                     break
301                 else:
302                     self.run_message_dialog(gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "You must enter a server address and username.")
303
304
305         dialog.hide()
306         return True
307
308     def write(self, string): #Make this class a writeable object. Used so we can redirect print statements
309         if string == '\n':
310             self.push_status_message(self.print_redirect_sring)
311             print >>sys.__stdout__, self.print_redirect_sring #also print the string normally
312             self.print_redirect_sring = ""
313         else:
314             self.print_redirect_sring += string
315
316     def push_status_message(self, message):
317         """Pushes a message to the status textview in the main tab. This function inserts a \"\\n\" for you."""
318         buffer = self.messages_textview.get_buffer()
319         text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
320         text += message + "\n"
321         buffer.set_text(text)
322
323         #scroll to the bottom
324         self.messages_textview.scroll_to_iter(buffer.get_end_iter(), 0.0)
325
326     def set_status(self, message):
327         self.statusbar.pop(0)
328         self.statusbar.push(0, message)
329         self.push_status_message(message)
330
331     def on_main_window_key_press_event(self, widget, event):
332         current_page = self.utilites_notebook.get_current_page()
333
334         if current_page == 1:
335             self.sam_window.on_key_press(widget, event)
336         elif current_page == 2:
337             self.srvsvc_window.on_key_press(widget, event)
338         elif current_page == 3:
339             self.regedit_window.on_key_press(widget, event)
340         elif current_page == 4:
341             self.svcctl_window.on_key_press(widget, event)
342         elif current_page == 5:
343             self.crontab_window.on_key_press(widget, event)
344
345     def on_utility_notebook_switch_page(self, widget, page, page_num):
346         if page_num == 0: #main page
347
348             #Menubar
349             children = self.menubar_viewport.get_children()
350             self.menubar_viewport.remove(children[0])
351             self.menubar_viewport.add(self.menubar)
352             self.menubar_viewport.show_all()
353             #Toolbar
354             children = self.toolbar_viewport.get_children()
355             self.toolbar_viewport.remove(children[0])
356             self.toolbar_viewport.add(self.toolbar)
357             self.toolbar_viewport.show_all()
358
359             self.update_sensitivity()
360
361         elif page_num == 1: #Sam page
362             if self.sam_viewport.child == None:
363                 self.init_sam_page()
364
365             #Menubar
366             children = self.menubar_viewport.get_children()
367             self.menubar_viewport.remove(children[0])
368             self.menubar_viewport.add(self.sam_window.menubar)
369             self.menubar_viewport.show_all()
370
371             #Toolbar
372             children = self.toolbar_viewport.get_children()
373             self.toolbar_viewport.remove(children[0])
374             self.toolbar_viewport.add(self.sam_window.toolbar)
375             self.toolbar_viewport.show_all()
376
377
378         elif page_num == 2: #Share page
379             if self.srvsvc_viewport.child == None:
380                 self.init_srvsvc_page()
381
382             #Menubar
383             children = self.menubar_viewport.get_children()
384             self.menubar_viewport.remove(children[0])
385             if self.srvsvc_init is False:
386                 self.srvsvc_window.menubar.reparent(self.menubar_viewport)
387                 self.srvsvc_init = True
388             else:
389                 self.menubar_viewport.add(self.srvsvc_window.menubar)
390             self.menubar_viewport.show_all()
391
392             #Toolbar
393             children = self.toolbar_viewport.get_children()
394             self.toolbar_viewport.remove(children[0])
395             self.srvsvc_window.toolbar.unparent()
396             self.toolbar_viewport.add(self.srvsvc_window.toolbar)
397             self.toolbar_viewport.show_all()
398
399             self.srvsvc_window.hide()
400
401         elif page_num == 3: #Regedit page
402             if self.regedit_viewport.child == None:
403                 self.init_regedit_page()
404
405             #Menubar
406             children = self.menubar_viewport.get_children()
407             self.menubar_viewport.remove(children[0])
408             self.menubar_viewport.add(self.regedit_window.menubar)
409             self.menubar_viewport.show_all()
410
411             #Toolbar
412             children = self.toolbar_viewport.get_children()
413             self.toolbar_viewport.remove(children[0])
414             self.toolbar_viewport.add(self.regedit_window.toolbar)
415             self.toolbar_viewport.show_all()
416
417         elif page_num == 4: #Services page
418             if self.svcctl_viewport.child == None:
419                 self.init_svcctl_page()
420
421             #Menubar
422             children = self.menubar_viewport.get_children()
423             self.menubar_viewport.remove(children[0])
424             self.menubar_viewport.add(self.svcctl_window.menubar)
425             self.menubar_viewport.show_all()
426
427             #Toolbar
428             children = self.toolbar_viewport.get_children()
429             self.toolbar_viewport.remove(children[0])
430             self.toolbar_viewport.add(self.svcctl_window.toolbar)
431             self.toolbar_viewport.show_all()
432
433         elif page_num == 5: #Crontab page
434             if self.crontab_viewport.child == None:
435                 self.init_crontab_page()
436
437             #Menubar
438             children = self.menubar_viewport.get_children()
439             self.menubar_viewport.remove(children[0])
440             self.menubar_viewport.add(self.crontab_window.menubar)
441             self.menubar_viewport.show_all()
442
443             #Toolbar
444             children = self.toolbar_viewport.get_children()
445             self.toolbar_viewport.remove(children[0])
446             self.toolbar_viewport.add(self.crontab_window.toolbar)
447             self.toolbar_viewport.show_all()
448
449     def on_connect_all_button_clicked(self, widget):
450
451         if self.connection_args.has_key("connect_now") and self.connection_args["connect_now"]:
452             #if the user specified --connect-now then we probably have enough arguments to connect
453
454             if self.sam_initialized():
455                 if not self.sam_window.connected():
456                     self.sam_window.on_connect_item_activate(None, **self.connection_args)
457             else:
458                 self.init_sam_page()
459
460             if self.srvsvc_initialized():
461                 if not self.srvsvc_window.connected():
462                     self.srvsvc_window.on_connect_item_activate(None, **self.connection_args)
463             else:
464                 self.init_srvsvc_page()
465
466             if self.regedit_initialized():
467                 if not self.regedit_window.connected():
468                     self.regedit_window.on_connect_item_activate(None, **self.connection_args)
469             else:
470                 self.init_regedit_page()
471
472             if self.svcctl_initialized():
473                 if not self.svcctl_window.connected():
474                     self.svcctl_window.on_connect_item_activate(None, **self.connection_args)
475             else:
476                 self.init_svcctl_page()
477
478             if self.crontab_initialized():
479                 if not self.crontab_window.connected():
480                     self.crontab_window.on_connect_item_activate(None, **self.connection_args)
481             else:
482                 self.init_crontab_page()
483
484         else:
485             if self.run_connect_all_dialog():
486                 self.on_connect_all_button_clicked(None)
487
488     def on_disconnect_all_button_clicked(self, widget):
489         if self.sam_initialized():
490             self.sam_window.on_disconnect_item_activate(None)
491         if self.srvsvc_initialized():
492             self.srvsvc_window.on_disconnect_item_activate(None)
493         if self.regedit_initialized():
494             self.regedit_window.on_disconnect_item_activate(None)
495         if self.svcctl_initialized():
496             self.svcctl_window.on_disconnect_item_activate(None)
497         if self.crontab_initialized():
498             self.crontab_window.on_disconnect_item_activate(None)
499         self.update_sensitivity()
500
501     def on_connection_info_item_activate(self, widget):
502         #TODO: display connection info (via a dialog or custom window?)
503         self.push_status_message("This is not implemented yet!")
504         pass
505
506     def on_clear_log_activate(self, widget):
507         self.messages_textview.get_buffer().set_text("")
508
509
510     def on_about_item_activate(self, widget):
511         dialog = AboutDialog(
512                              "Main",
513                              "A tool to display other utilities in a simple, unified window.",
514                              None
515                              )
516         dialog.run()
517         dialog.hide()
518
519
520     def on_quit_item_activate(self, widget):
521         gtk.main_quit()
522
523 #************ END OF CLASS ***************
524
525 def PrintUseage():
526     print "Usage: %s [OPTIONS]" % (str(os.path.split(__file__)[-1]))
527     print "All options are optional. The user will be queried for additional information if needed.\n"
528     print "  -s  --server\t\tspecify the server to connect to."
529     print "  -u  --user\t\tspecify the user."
530     print "  -p  --password\tThe password for the user."
531     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."
532     print "  -c  --connect-now\tSkip the connect dialog."
533
534 def ParseArgs(argv):
535     arguments = {}
536
537     try: #get arguments into a nicer format
538         opts, args = getopt.getopt(argv, "chu:s:p:t:", ["help", "user=", "server=", "password=", "connect-now", "transport="])
539     except getopt.GetoptError:
540         PrintUseage()
541         sys.exit(2)
542
543     for opt, arg in opts:
544         if opt in ("-h", "--help"):
545             PrintUseage()
546             sys.exit(0)
547         elif opt in ("-s", "--server"):
548             arguments.update({"server":arg})
549         elif opt in ("-u", "--user"):
550             arguments.update({"username":arg})
551         elif opt in ("-p", "--password"):
552             arguments.update({"password":arg})
553         elif opt in ("-t", "--transport"):
554             arguments.update({"transport_type":int(arg)})
555         elif opt in ("-c", "--connect-now"):
556             arguments.update({"connect_now":True})
557     return (arguments)
558
559
560 if __name__ == "__main__":
561     arguments = ParseArgs(sys.argv[1:])
562     gtk.gdk.threads_init()
563     main_window = SambaUtilities(arguments)
564     sys.stdout = main_window #redirect print statements to the write() function of this class
565     gtk.main()
566