Package conduit :: Package gtkui :: Module UI
[hide private]

Source Code for Module conduit.gtkui.UI

  1  """ 
  2  Draws the applications main window 
  3   
  4  Also manages the callbacks from menu and GUI items 
  5   
  6  Copyright: John Stowers, 2006 
  7  License: GPLv2 
  8  """ 
  9  import gobject 
 10  import gtk, gtk.glade 
 11  import gnome.ui 
 12  import os.path 
 13  import gettext 
 14  import threading 
 15  from gettext import gettext as _ 
 16  import logging 
 17  log = logging.getLogger("gtkui.UI") 
 18   
 19  import conduit 
 20  import conduit.Web as Web 
 21  import conduit.Conduit as Conduit 
 22  import conduit.gtkui.Canvas as Canvas 
 23  import conduit.gtkui.MsgArea as MsgArea 
 24  import conduit.gtkui.Tree as Tree 
 25  import conduit.gtkui.ConflictResolver as ConflictResolver 
 26  import conduit.gtkui.Database as Database 
 27   
 28   
 29  DEFAULT_CONDUIT_BROWSER = "gtkmozembed" 
 30  DEVELOPER_WEB_LINKS = ( 
 31  #name,                      #url 
 32  ("Introduction",            "http://www.conduit-project.org/wiki/Development"), 
 33  ("Writing a Data Provider", "http://www.conduit-project.org/wiki/WritingADataProvider"), 
 34  ("API Documentation",       "http://doc.conduit-project.org/conduit/"), 
 35  ("Test Results",            "http://tests.conduit-project.org/") 
 36  ) 
 37   
 38  #set up the gettext system and locales 
 39  for module in gtk.glade, gettext: 
 40      module.bindtextdomain('conduit', conduit.LOCALE_DIR) 
 41      module.textdomain('conduit') 
 42       
43 -class MainWindow:
44 """ 45 The main conduit window. 46 """
47 - def __init__(self, conduitApplication, moduleManager, typeConverter, syncManager):
48 """ 49 Constructs the mainwindow. Throws up a splash screen to cover 50 the most time consuming pieces 51 """ 52 gnome.ui.authentication_manager_init() 53 54 self.conduitApplication = conduitApplication 55 56 #add some additional dirs to the icon theme search path so that 57 #modules can provider their own icons 58 icon_dirs = [ 59 conduit.SHARED_DATA_DIR, 60 conduit.SHARED_MODULE_DIR, 61 os.path.join(conduit.SHARED_DATA_DIR,"icons"), 62 os.path.join(conduit.USER_DIR, "modules") 63 ] 64 for i in icon_dirs: 65 gtk.icon_theme_get_default().prepend_search_path(i) 66 67 self.gladeFile = os.path.join(conduit.SHARED_DATA_DIR, "conduit.glade") 68 self.widgets = gtk.glade.XML(self.gladeFile, "MainWindow") 69 70 dic = { "on_mainwindow_delete" : self.on_window_closed, 71 "on_mainwindow_state_event" : self.on_window_state_event, 72 "on_synchronize_activate" : self.on_synchronize_all_clicked, 73 "on_cancel_activate" : self.on_cancel_all_clicked, 74 "on_quit_activate" : self.on_window_closed, 75 "on_clear_canvas_activate" : self.on_clear_canvas, 76 "on_preferences_activate" : self.on_conduit_preferences, 77 "on_about_activate" : self.on_about_conduit, 78 "on_contents_activate" : self.on_help, 79 "on_save1_activate" : self.save_settings, 80 None : None 81 } 82 self.widgets.signal_autoconnect(dic) 83 84 #type converter and sync manager 85 self.type_converter = typeConverter 86 self.sync_manager = syncManager 87 88 #Initialize the mainWindow 89 self.mainWindow = self.widgets.get_widget("MainWindow") 90 #Enable RGBA colormap 91 if conduit.GLOBALS.settings.get("gui_use_rgba_colormap") == True: 92 screen = self.mainWindow.get_screen() 93 colormap = screen.get_rgba_colormap() 94 if colormap: 95 gtk.widget_set_default_colormap(colormap) 96 self.mainWindow.set_position(gtk.WIN_POS_CENTER) 97 self.mainWindow.set_icon_name("conduit") 98 title = "Conduit" 99 if conduit.IS_DEVELOPMENT_VERSION: 100 title = title + " - %s (Development Version)" % conduit.VERSION 101 if not conduit.IS_INSTALLED: 102 title = title + " - Running Uninstalled" 103 self.mainWindow.set_title(title) 104 105 #Configure canvas 106 self.canvasSW = self.widgets.get_widget("canvasScrolledWindow") 107 self.hpane = self.widgets.get_widget("hpaned1") 108 109 #start up the canvas 110 msg = MsgArea.MsgAreaController() 111 self.widgets.get_widget("mainVbox").pack_start(msg, False, False) 112 self.canvas = Canvas.Canvas( 113 parentWindow=self.mainWindow, 114 typeConverter=self.type_converter, 115 syncManager=self.sync_manager, 116 dataproviderMenu=gtk.glade.XML(self.gladeFile, "DataProviderMenu"), 117 conduitMenu=gtk.glade.XML(self.gladeFile, "ConduitMenu"), 118 msg=msg 119 ) 120 self.canvasSW.add(self.canvas) 121 self.canvas.connect('drag-drop', self.drop_cb) 122 self.canvas.connect("drag-data-received", self.drag_data_received_data) 123 124 # Populate the tree model 125 self.dataproviderTreeModel = Tree.DataProviderTreeModel() 126 dataproviderScrolledWindow = self.widgets.get_widget("scrolledwindow2") 127 self.dataproviderTreeView = Tree.DataProviderTreeView(self.dataproviderTreeModel) 128 dataproviderScrolledWindow.add(self.dataproviderTreeView) 129 130 #Set up the expander used for resolving sync conflicts 131 self.conflictResolver = ConflictResolver.ConflictResolver(self.widgets) 132 133 #final GUI setup 134 self.cancelSyncButton = self.widgets.get_widget('cancel') 135 self.hpane.set_position(conduit.GLOBALS.settings.get("gui_hpane_postion")) 136 self.dataproviderTreeView.set_expand_rows() 137 self.window_state = 0 138 139 #if running a development version, add some developer specific links 140 #to the help menu 141 if conduit.IS_DEVELOPMENT_VERSION: 142 helpMenu = self.widgets.get_widget("help_menu") 143 developersMenuItem = gtk.ImageMenuItem("Developers") 144 developersMenuItem.set_image( 145 gtk.image_new_from_icon_name( 146 "applications-development", 147 gtk.ICON_SIZE_MENU)) 148 developersMenu = gtk.Menu() 149 developersMenuItem.set_submenu(developersMenu) 150 helpMenu.prepend(developersMenuItem) 151 for name,url in DEVELOPER_WEB_LINKS: 152 item = gtk.ImageMenuItem(name) 153 item.set_image( 154 gtk.image_new_from_icon_name( 155 "applications-internet", 156 gtk.ICON_SIZE_MENU)) 157 item.connect("activate",self.on_developer_menu_item_clicked,name,url) 158 developersMenu.append(item)
159 160
161 - def on_developer_menu_item_clicked(self, menuitem, name, url):
162 threading.Thread( 163 target=Web.LoginMagic, 164 args=(name, url), 165 kwargs={"login_function":lambda: True} 166 ).start()
167
168 - def on_conduit_added(self, syncset, cond):
169 cond.connect("sync-started", self.on_sync_started) 170 cond.connect("sync-completed", self.on_sync_completed) 171 cond.connect("sync-conflict", self.conflictResolver.on_conflict)
172
173 - def set_model(self, syncSet):
174 self.syncSet = syncSet 175 self.syncSet.connect("conduit-added", self.on_conduit_added) 176 self.canvas.set_sync_set(syncSet)
177
178 - def present(self):
179 """ 180 Present the main window. Enjoy your window 181 """ 182 log.debug("Presenting GUI") 183 self.mainWindow.show_all() 184 self.mainWindow.present()
185
186 - def minimize_to_tray(self):
187 """ 188 Iconifies the main window 189 """ 190 log.debug("Iconifying GUI") 191 self.mainWindow.hide()
192
193 - def is_visible(self):
194 """ 195 Returns True if mainWindow is visible 196 (not minimized or withdrawn) 197 """ 198 minimized = self.window_state & gtk.gdk.WINDOW_STATE_ICONIFIED 199 return (not minimized) and self.mainWindow.get_property('visible')
200
201 - def on_sync_started(self, thread):
202 self.cancelSyncButton.set_property("sensitive", True)
203
204 - def on_sync_completed(self, thread, aborted, error, conflict):
205 self.cancelSyncButton.set_property( 206 "sensitive", 207 conduit.GLOBALS.syncManager.is_busy() 208 )
209
210 - def on_synchronize_all_clicked(self, widget):
211 """ 212 Synchronize all valid conduits on the canvas 213 """ 214 self.conduitApplication.Synchronize()
215
216 - def on_cancel_all_clicked(self, widget):
217 """ 218 Cancels all currently runnings syncs 219 """ 220 self.conduitApplication.Cancel()
221
222 - def on_clear_canvas(self, widget):
223 """ 224 Clear the canvas and start a new sync set 225 """ 226 self.canvas.clear_canvas()
227
228 - def on_conduit_preferences(self, widget):
229 """ 230 Show the properties of the current sync set (status, conflicts, etc 231 Edit the sync specific properties 232 """ 233 def on_clear_button_clicked(sender, treeview, sqliteListStore): 234 treeview.set_model(None) 235 conduit.GLOBALS.mappingDB.delete() 236 treeview.set_model(sqliteListStore)
237 238 #Build some liststores to display 239 CONVERT_FROM_MESSAGE = _("Convert from") 240 CONVERT_INTO_MESSAGE = _("into") 241 242 convertables = self.type_converter.get_convertables_list() 243 converterListStore = gtk.ListStore( str ) 244 for froms,tos in convertables: 245 string = "%s %s %s %s" % (CONVERT_FROM_MESSAGE, froms, CONVERT_INTO_MESSAGE, tos) 246 converterListStore.append( (string,) ) 247 dataProviderListStore = gtk.ListStore( str, bool ) 248 #get all dataproviders 249 for i in conduit.GLOBALS.moduleManager.get_modules_by_type("sink","source","twoway"): 250 dataProviderListStore.append(("Name: %s\nDescription: %s)" % (i.name, i.description), True)) 251 #include files that could not be loaded 252 for f in conduit.GLOBALS.moduleManager.invalidFiles: 253 dataProviderListStore.append(("Error loading file: %s" % f, False)) 254 255 #construct the dialog 256 tree = gtk.glade.XML(self.gladeFile, "PreferencesDialog") 257 notebook = tree.get_widget("prop_notebook") 258 259 #Show the DB contents to help debugging 260 if conduit.IS_DEVELOPMENT_VERSION: 261 vbox = gtk.VBox(False,5) 262 263 #build the treeview to show all column fields. For performance 264 #reasons it is fixed_height and fixed_FIXE 265 treeview = gtk.TreeView() 266 treeview.set_headers_visible(True) 267 treeview.set_fixed_height_mode(True) 268 index = 1 269 db = conduit.GLOBALS.mappingDB._db 270 for name in db.get_fields("mappings"): 271 column = gtk.TreeViewColumn( 272 name, 273 gtk.CellRendererText(), 274 text=index) 275 column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) 276 column.set_fixed_width(250) 277 treeview.append_column(column) 278 index = index + 1 279 280 store = Database.GenericDBListStore("mappings", db) 281 treeview.set_model(store) 282 283 sw = gtk.ScrolledWindow() 284 sw.add(treeview) 285 vbox.pack_start(sw,True,True) 286 287 clear = gtk.Button(None,gtk.STOCK_CLEAR) 288 clear.connect("clicked", on_clear_button_clicked, treeview, store) 289 vbox.pack_start(clear, False, False) 290 291 notebook.append_page(vbox,gtk.Label(_('Relationship Database'))) 292 293 converterTreeView = tree.get_widget("dataConversionsTreeView") 294 converterTreeView.set_model(converterListStore) 295 converterTreeView.append_column(gtk.TreeViewColumn(_("Conversions Available"), 296 gtk</