page swaps fixed
[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
16
17 import pygwsam
18 import pygwregedit
19 import pygwcrontab
20 import pygwsvcctl
21 import pygwshare
22
23 from sambagtk.dialogs import AboutDialog
24 from sambagtk.sam import SAMConnectDialog
25 from sambagtk.pysrvsvc import srvsvcConnectDialog
26
27
28 class SambaUtilities(object):
29
30     def __init__(self, connection_args={}, additional_connection_arguments={}):
31
32         self.create()
33
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
43
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 = ""
48
49         self.update_sensitivity()
50         self.window.show()
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
53
54         if (connection_args.has_key("connect_now") and connection_args["connect_now"]):
55             self.on_connect_all_button_clicked(None)
56
57
58     def create(self):
59         # get a builder and put it to work
60         builder = gtk.Builder()
61         builder.add_from_file("main.glade")
62
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,
66
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,
73
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,
77
78                        "on_utility_notebook_switch_page": self.on_utility_notebook_switch_page,
79
80                        }
81         #Make the connections
82         builder.connect_signals(connections)
83
84         #Handles
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")
90
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")
95
96         self.utilites_notebook = builder.get_object("utility_notebook")
97
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")
102
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")
108
109         self.progressbar = builder.get_object("progressbar")
110         self.statusbar = builder.get_object("statusbar")
111
112
113     def init_sam_page(self):
114
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"]})
120
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
124
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
129
130         self.set_status("User tab initialized.")
131         self.update_sensitivity()
132
133     def init_srvsvc_page(self):
134
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"]})
138
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
142
143         #We'll be displaying this later. We need to unparent it before attaching it to another container
144
145         self.srvsvc_window.toolbar.unparent()
146         self.srvsvc_window.statusbar = self.statusbar #we simply tell the utility to use our status bar instead
147
148         self.set_status("Share Manager tab initialized.")
149         self.update_sensitivity()
150
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
158
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
163
164         self.set_status("Regedit tab initialized.")
165         self.update_sensitivity()
166
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
174
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
179
180         self.set_status("Services tab initialized.")
181         self.update_sensitivity()
182
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
190
191         self.crontab_window.menubar.unparent()
192         self.crontab_window.toolbar.unparent()
193         self.crontab_window.statusbar = self.statusbar
194
195         self.set_status("Scheduled tasks tab initialized.")
196         self.update_sensitivity()
197
198     def sam_initialized(self):
199         return self.sam_window is not None
200
201     def regedit_initialized(self):
202         return self.regedit_window is not None
203
204     def srvsvc_initialized (self):
205         return self.srvsvc_window is not None
206
207     def svcctl_initialized(self):
208         return self.svcctl_window is not None
209
210     def crontab_initialized(self):
211         return self.crontab_window is not None
212
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)
221
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)
226
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")
229         if (all_connected):
230             self.status_label.set_text("All connected")
231         elif (all_disconnected):
232             self.status_label.set_text("All disconnected")
233         else:
234             connected_utilities = []
235             if sam_connected:
236                 connected_utilities.append("User Manager")
237             if srvsvc_connected:
238                 connected_utilities.append("Share Manager")
239             if regedit_connected:
240                 connected_utilities.append("Registry Editor")
241             if svcctl_connected:
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."))
248
249     def server_info_callback(self, server = "", username = "", transport_type = None):
250         if server:
251             self.connection_args.update({"server":server})
252         if username:
253             self.connection_args.update({"username":username})
254         if transport_type:
255             self.connection_args.update({"transport_type":transport_type})
256
257     def run_message_dialog(self, type, buttons, message, parent = None):
258         if (parent == None):
259             parent = self.window
260
261         message_box = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, type, buttons, message)
262         response = message_box.run()
263         message_box.hide()
264
265         return response
266
267     def run_connect_all_dialog(self):
268         """Runs the connection dialog and saves connection arguments to self.connection_args
269
270         returns True if arguments were uptained successfully"""
271         #TODO in this function: handle domain selection
272         args = {}
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]})
277
278         dialog = SAMConnectDialog(**args)
279         dialog.show_all()
280
281         # loop to handle the failures
282         while True:
283             response_id = dialog.run()
284
285             if (response_id != gtk.RESPONSE_OK):
286                 dialog.hide()
287                 return False
288             else:
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
298                     break
299                 else:
300                     self.run_message_dialog(gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "You must enter a server address and username.")
301
302
303         dialog.hide()
304         return True
305
306     def write(self, string): #Make this class a writeable object. Used so we can redirect print statements
307         if string == '\n':
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 = ""
311         else:
312             self.print_redirect_sring += string
313
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)
320
321         #scroll to the bottom
322         self.messages_textview.scroll_to_iter(buffer.get_end_iter(), 0.0)
323
324     def set_status(self, message):
325         self.statusbar.pop(0)
326         self.statusbar.push(0, message)
327         self.push_status_message(message)
328
329     def on_main_window_key_press_event(self, widget, event):
330         current_page = self.utilites_notebook.get_current_page()
331
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)
342
343     def on_utility_notebook_switch_page(self, widget, page, page_num):
344         if page_num == 0: #main page
345
346             #Menubar
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()
351             #Toolbar
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()
356
357             self.update_sensitivity()
358
359         elif page_num == 1: #Sam page
360             if self.sam_viewport.child == None:
361                 self.init_sam_page()
362
363             #Menubar
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()
368
369             #Toolbar
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()
374
375
376         elif page_num == 2: #Share page
377             if self.srvsvc_viewport.child == None:
378                 self.init_srvsvc_page()
379
380             #Menubar
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
386             else:
387                 self.menubar_viewport.add(self.srvsvc_window.menubar)
388             self.menubar_viewport.show_all()
389
390             #Toolbar
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()
396
397             self.srvsvc_window.hide()
398
399         elif page_num == 3: #Regedit page
400             if self.regedit_viewport.child == None:
401                 self.init_regedit_page()
402
403             #Menubar
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()
408
409             #Toolbar
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()
414
415         elif page_num == 4: #Services page
416             if self.svcctl_viewport.child == None:
417                 self.init_svcctl_page()
418
419             #Menubar
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()
424
425             #Toolbar
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()
430
431         elif page_num == 5: #Crontab page
432             if self.crontab_viewport.child == None:
433                 self.init_crontab_page()
434
435             #Menubar
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()
440
441             #Toolbar
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()
446
447     def on_connect_all_button_clicked(self, widget):
448
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
451
452             if self.sam_initialized():
453                 if not self.sam_window.connected():
454                     self.sam_window.on_connect_item_activate(None, **self.connection_args)
455             else:
456                 self.init_sam_page()
457
458             if self.srvsvc_initialized():
459                 if not self.srvsvc_window.connected():
460                     self.srvsvc_window.on_connect_item_activate(None, **self.connection_args)
461             else:
462                 self.init_srvsvc_page()
463
464             if self.regedit_initialized():
465                 if not self.regedit_window.connected():
466                     self.regedit_window.on_connect_item_activate(None, **self.connection_args)
467             else:
468                 self.init_regedit_page()
469
470             if self.svcctl_initialized():
471                 if not self.svcctl_window.connected():
472                     self.svcctl_window.on_connect_item_activate(None, **self.connection_args)
473             else:
474                 self.init_svcctl_page()
475
476             if self.crontab_initialized():
477                 if not self.crontab_window.connected():
478                     self.crontab_window.on_connect_item_activate(None, **self.connection_args)
479             else:
480                 self.init_crontab_page()
481
482         else:
483             if self.run_connect_all_dialog():
484                 self.on_connect_all_button_clicked(None)
485
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()
498
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!")
502         pass
503
504     def on_clear_log_activate(self, widget):
505         self.messages_textview.get_buffer().set_text("")
506
507
508     def on_about_item_activate(self, widget):
509         dialog = AboutDialog(
510                              "Main",
511                              "A tool to display other utilities in a simple, unified window.",
512                              None
513                              )
514         dialog.run()
515         dialog.hide()
516
517
518     def on_quit_item_activate(self, widget):
519         gtk.main_quit()
520
521 #************ END OF CLASS ***************
522
523 def PrintUseage():
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."
531
532 def ParseArgs(argv):
533     arguments = {}
534
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:
538         PrintUseage()
539         sys.exit(2)
540
541     for opt, arg in opts:
542         if opt in ("-h", "--help"):
543             PrintUseage()
544             sys.exit(0)
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})
555     return (arguments)
556
557
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
563     gtk.main()
564