class _DownloadStatus(HBox): def __init__(self, queue): HBox.__init__(self) self.thread = DlWorker(queue, self.progress, self.set_url) self.label = Label('hello') self.pbar = ProgressBar() self.pack_start(self.label, FALSE, FALSE, 0) self.pack_end(self.pbar, FALSE, FALSE, 0) self.label.show() self.pbar.show() self.show() self._done = False self._started = False def progress(self, dt, dd, ut, ud): threads_enter() print 'in progress', dt, dd, ut, ud if dt == 0: self._done += 0.1 if self._done >= 1: self._done = 0 else: self._done = float(dd) / float(dt) print '_done', self._done self.pbar.set_fraction(self._done) threads_leave() def set_url(self, url): self.label.set_text(url) def start(self, *args): if not self._started: self.thread.start() self._started = True
class _DownloadStatus(HBox): def __init__(self, queue): HBox.__init__(self) self.thread = DlWorker(queue, self.progress, self.set_url) self.label = Label("hello") self.pbar = ProgressBar() self.pack_start(self.label, FALSE, FALSE, 0) self.pack_end(self.pbar, FALSE, FALSE, 0) self.label.show() self.pbar.show() self.show() self._done = False self._started = False def progress(self, dt, dd, ut, ud): threads_enter() print "in progress", dt, dd, ut, ud if dt == 0: self._done += 0.1 if self._done >= 1: self._done = 0 else: self._done = float(dd) / float(dt) print "_done", self._done self.pbar.set_fraction(self._done) threads_leave() def set_url(self, url): self.label.set_text(url) def start(self, *args): if not self._started: self.thread.start() self._started = True
class PresenceServiceNameWatcher(VBox): def __init__(self, bus): VBox.__init__(self) self.bus = bus logger.debug('Running...') self.label = Label('Looking for Presence Service...') self.errors = ListStore(str) errors_tree = TreeView(model=self.errors) errors_tree.insert_column_with_attributes(0, 'Log', CellRendererText(), text=0) scroller = ScrolledWindow() scroller.add(errors_tree) self.paned = VPaned() self.paned.pack1(scroller) self.pack_start(self.label, False, False) self.pack_end(self.paned) bus.watch_name_owner(PS_NAME, self.on_name_owner_change) self.ps_watcher = Label('-') self.paned.pack2(self.ps_watcher) self.show_all() def log(self, format, *args): self.errors.append((format % args, )) def on_name_owner_change(self, owner): try: if owner: self.label.set_text( 'Presence Service running: unique name %s' % owner) if self.ps_watcher is not None: self.paned.remove(self.ps_watcher) self.ps_watcher = PresenceServiceWatcher( self.bus, owner, self.log) self.paned.pack2(self.ps_watcher) self.show_all() else: self.label.set_text('Presence Service not running') if self.ps_watcher is not None: self.paned.remove(self.ps_watcher) self.ps_watcher = Label('-') self.paned.pack2(self.ps_watcher) except Exception, e: self.log('ERROR: %s', e)
class Requeriment(Expander): def __init__(self, objectives, new): Expander.__init__(self) self.connect("enter-notify-event", self.onEnterNotifyEvent) self.connect("leave-notify-event", self.onLeaveNotifyEvent) vBox = VBox() self.add(vBox) # Data model self.model = ListStore(str, float) # Title bar hBox = HBox() self.set_property("label-widget", hBox) self.title = Label() hBox.pack_start(self.title) # Alternatives treeView = TreeView(self.model) # treeView.set_headers_visible(False) vBox.pack_start(treeView) listStore_objectives = ListStore(str) for name in objectives: listStore_objectives.append((name, )) def combo_changed(_, path, text, model): model[path][0] = text cellRenderer = CellRendererCombo() cellRenderer.connect("edited", combo_changed, self.model) cellRenderer.set_property("text-column", 0) cellRenderer.set_property("editable", True) cellRenderer.set_property("has-entry", True) cellRenderer.set_property("model", listStore_objectives) treeViewColumn = TreeViewColumn("Alternative", cellRenderer, text=0) # treeViewColumn = TreeViewColumn(None,cellRenderer,text=0) treeView.append_column(treeViewColumn) def spin_changed(_, path, value, model): model[path][1] = float(value.replace(",", ".")) cellRenderer = CellRendererSpin() cellRenderer.connect("edited", spin_changed, self.model) cellRenderer.set_property("adjustment", Adjustment(1, 0, 100, 1, 10, 0)) cellRenderer.set_property("editable", True) cellRenderer.set_property("digits", 2) treeViewColumn = TreeViewColumn(None, cellRenderer, text=1) treeView.append_column(treeViewColumn) # Add/remove alternative button box # hButtonBox = HButtonBox() # vBox.pack_start(hButtonBox, False) # Add alternative button = Button("gtk-add") button.connect("clicked", self.on_btnAdd_Alternative_clicked) button.set_use_stock(True) # hButtonBox.pack_start(button) vBox.pack_start(button, False) # # Remove alternative # button = Button("gtk-remove") # button.connect("clicked",self.on_btnDel_Alternative_clicked) # button.set_use_stock(True) # hButtonBox.pack_start(button) # Expand the requeriment and add an alternative if it's new if new: self.set_expanded(True) self.model.append((None, 1.0)) # Show requeriment self.show_all() # Delete requeriment button (default is hidden) self.imgRemove = Image() self.imgRemove.connect("button-press-event", self.onDelRequeriment) self.imgRemove.set_from_stock("gtk-cancel", ICON_SIZE_MENU) hBox.pack_start(self.imgRemove) def Add(self, alternative): self.model.append(alternative) names = [] iter = self.model.get_iter_first() while iter: alt = self.model.get_value(iter, 0) if alt: names.append(alt) iter = self.model.iter_next(iter) self.title.set_text(','.join(names)) def GetData(self): result = OrderedDict() iter = self.model.get_iter_first() while iter: alt = self.model.get_value(iter, 0) if alt: result[alt] = self.model.get_value(iter, 1) iter = self.model.iter_next(iter) return result def onDelRequeriment(self, widget): self.get_parent().remove(self) def onEnterNotifyEvent(self, widget, event): self.imgRemove.show() def onLeaveNotifyEvent(self, widget, event): self.imgRemove.hide() def __btnDel_Alternative_Sensitivity(self): pass # self.__btnDel.set_sensitive(len(self.__model.)) def on_btnAdd_Alternative_clicked(self, widget): self.model.append((None, 1.0)) self.__btnDel_Alternative_Sensitivity() def on_btnDel_Alternative_clicked(self, widget): self.__btnDel_Alternative_Sensitivity()
class multipage_glade_editor(object): def __init__(self, trans, transid, plugin, gui_parent, change_register_function, book, display_mode=TRANSACTION_ALL_EDIT_FIRST_TIME, transaction_edit_finished_function=null_function): self.trans = trans self.transid = transid self.plugin = plugin self.gui_parent = gui_parent self.change_register_function = change_register_function self.book = book self.display_mode = display_mode self.transaction_edit_finished_function = ( null_function if display_mode not in HEADLESS_MODES else transaction_edit_finished_function ) self.hide_parent = Window() self.hide_parent.hide() self.mainvbox = VBox() self.hide_parent.add(self.mainvbox) config = self.trans.get_configuration_and_provide_on_load_hook() config_module_name = self.plugin.config_module_name if not config_valid(config): # even in the case of a broken config, we should still # display all of the data we have available... self.mainvbox.pack_start(Label("no configuration")) elif not self.trans.can_safely_proceed_with_config_module(config): # should display all data that's available instead of just # this label # # and should give # user an overide option where they either pick an old config # for one time use or just blow out the memory of having used # a different config... # # should also print the checksum itself so they know # what they need... # # perhaps eventually we even put in place some archival support # for saving old glade and config files and then code into the # the transaction -- hey, code you need to be editable is # over here.. # # now hopefully there is no marking of this transaction dirty # in this mode and the extra safegaurds we put into # MultipageGladeTransaction don't get activated self.mainvbox.pack_start( Label("out of date configuration. data is read only here for " "the safety of your old information, last adler " "CRC was %s" % self.trans.config_crc_cache )) else: # if the safety cache was relied on before we need to tell the # backend that the transaction is actually dirty, # and now that we know that we have a workable config, # there's a chance that we'll actually be able to avoid # relying on the cache this time if self.trans.get_safety_cache_was_used(): self.change_register_function() self.page_label = Label("") (x_align, y_align) = self.page_label.get_alignment() self.page_label.set_alignment(0.0, y_align) self.mainvbox.pack_start(self.page_label, expand=False) # establish maincontainer, which is where the actual glade # pages are put by attach_current_page # # The order of placement here is important, we place this # after page_label has already been added to main # and we also need to do this prior to attach_current_page # being called, as it depends on self.maincontainer being # there # # when we're in headless mode the maincontainer can just be # the mainvbox itself # # but, outside headless mode we save screen real-estate and # place a scrolled window (which becomes the maincontainer) # inside the mainvbox and the glade by glade pages end up # in there instead (again, in attach_current_page) if display_mode in HEADLESS_MODES: self.maincontainer = self.mainvbox else: self.maincontainer = Viewport() sw = ScrolledWindow() sw.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) sw.add( self.maincontainer) self.mainvbox.pack_start(sw) self.glade_pages = [ self.__setup_page(glade_file, top_glade_element) for glade_file, top_glade_element in config.pages ] self.glade_pages_by_ident_index = dict( ( (key, self.glade_pages[i]) for i, key in enumerate(config.pages) ) # end generator expression ) # end dict self.__setup_auto_widgets() self.current_page = 0 self.attach_current_page() button_hbox = HBox() self.mainvbox.pack_end(button_hbox, expand=False) self.nav_buts = dict( (Button(), i) for i in range(2) ) for but, i in self.nav_buts.iteritems(): but.set_property('use-stock', True) but.set_label( STOCK_GO_BACK if i == GLADE_BACK_NAV else STOCK_GO_FORWARD ) button_hbox.pack_start(but, expand=False) but.connect("clicked", self.nav_but_clicked) config.gui_initialization_hook( self, self.trans, self.plugin, self.book) self.mainvbox.show_all() self.mainvbox.reparent(self.gui_parent) def page_is_current(self, page): # assumption is that config is fine and we're on a page assert( hasattr(self, 'glade_pages_by_ident_index') and True ) return \ self.glade_pages_by_ident_index[page] == self.current_widget_dict def __setup_page(self, glade_file, top_glade_element): widget_dict = {} # this should come from the config, seeing how we're setting up # our stuff manually event_handlers_dict = {} load_glade_file_get_widgets_and_connect_signals( glade_file, top_glade_element, widget_dict, event_handlers_dict ) widget_dict[top_glade_element].hide() return widget_dict def __setup_auto_widgets(self): # go through each page for key, widget_dict in self.glade_pages_by_ident_index.iteritems(): # go through each widget for widget_name, widget in widget_dict.iteritems(): widget_key = (key, widget_name) # determine if the current widget is one that we can take # care of automatically saving, we do this with a linear # search through a table of eligible types, # where the first element of each entry is Widget class # # Once we have a match do one of the following # * Change the widget from the existing stored stage # * Establish new state from some default # The next two entries in the table # (change_widget_from_state, new_state_from_widget) # provide functions to do this # # Lastly, we establish event handlers for this widget using # the last element in the table for (cls, change_widget_from_state, new_state_from_widget, establish_event_handlers) in ( # start table (Entry, lambda w, wk: w.set_text(self.trans.get_widget_state(wk)), lambda w: '', lambda w: w.connect("changed", self.entry_changed), ), # Entry (Calendar, self.__change_calendar_from_saved_version, get_current_date_of_gtkcal, lambda w: w.connect( "day_selected", self.calendar_changed ), ), # Calendar (CheckButton, lambda w, wk: w.set_active(self.trans.get_widget_state(wk)), get_state_of_checkbutton, lambda w: w.connect("toggled", self.checkbutton_changed), ), # CheckButton ): # end of table and for declartion # does the widget match the type in the current table entry? if isinstance(widget, cls): # use the three remaining functions in the table # as appropriate if self.trans.has_widget_state( widget_key ): change_widget_from_state(widget, widget_key) else: self.trans.update_widget_state( widget_key, new_state_from_widget(widget) ) establish_event_handlers(widget) def __change_calendar_from_saved_version(self, widget, widget_key): set_current_date_of_gtkcal(widget, self.trans.get_widget_state( widget_key ) ) def attach_current_page(self): config = self.plugin.get_configuration(allow_reload=False) self.current_widget_dict = self.glade_pages[self.current_page] self.current_window = self.current_widget_dict[ config.pages[self.current_page][TOP_WIDGET] ] self.current_top_vbox = self.current_window.child self.current_top_vbox.reparent( self.maincontainer) self.page_label.set_text( "page %s of %s" %( self.current_page + 1, len(config.pages) ) ) self.update_auto_labels() def detach_current_page(self): # put the spawn back to wence it came self.current_top_vbox.reparent( self.current_window) def detach(self): if hasattr(self, 'current_page'): self.detach_current_page() self.mainvbox.reparent(self.hide_parent) def page_change_acceptable_by_input_valid(self): bad_fields = ', '.join( widget_name for widget_name, widget in self.current_widget_dict.iteritems() if not self.widget_valid(widget_name, widget) ) if bad_fields == '': return True else: # this is kind of primiative, it would be better to # just highlight them by inserting red lights or something gtk_error_message("The following fields are invalid %s" % bad_fields ) return False def __current_page_ident(self): config = self.plugin.get_configuration(allow_reload=False) return config.pages[self.current_page] def __entry_widget_is_check_excempt(self, widget_name): config = self.plugin.get_configuration(allow_reload=False) return (self.__current_page_ident(), widget_name) in \ config.non_decimal_check_labels def widget_valid(self, widget_name, widget): config = self.plugin.get_configuration(allow_reload=False) if isinstance(widget, Entry) and \ not self.__entry_widget_is_check_excempt(widget_name): try: entry_to_decimal_convert( widget.get_text(), widget_name, self.__current_page_ident(), config) except EntryTextToDecimalConversionFail: return False # this covers not only the else case on the first if, but the # the case with the above try, except passes without exception return True def nav_but_clicked(self, but, *args): config = self.plugin.get_configuration(allow_reload=False) old_page = self.current_page delta = -1 if self.nav_buts[but] == GLADE_BACK_NAV else 1 new_page = old_page + delta # reject a change outside the acceptable range.. and hmm, # perhaps this event handler should never even run under those # conditions because we should really just grey the buttons if not (new_page < 0 or new_page == len(self.glade_pages)) and \ self.page_change_acceptable_by_input_valid() and \ config.page_change_acceptable(self.trans, old_page, new_page): # intentionally done before the page is actually attached, # that's what we mean by pre config.page_pre_change_config_hooks(self.trans, old_page, new_page) self.detach_current_page() self.current_page = new_page self.attach_current_page() # intentionally done after the page is actually attached, # that's what we mean by post config.page_post_change_config_hooks(self.trans, old_page, new_page) entry_changed = make_widget_changed_func(lambda w: w.get_text() ) calendar_changed = make_widget_changed_func(get_current_date_of_gtkcal) checkbutton_changed = make_widget_changed_func(get_state_of_checkbutton) def update_auto_labels(self): config = self.plugin.get_configuration(allow_reload=False) # this function should never be called if the config hasn't been # checked out as okay assert( hasattr(config, 'auto_update_labels') ) for page, label_name, label_source_func in config.auto_update_labels: if self.page_is_current(page): try: label_text = str(label_source_func( self.trans.widget_states, config)) except EntryTextToDecimalConversionFail, e: label_text = '' except WidgetFindError, no_find_e: label_text = str(no_find_e) self.current_widget_dict[label_name].set_text(label_text)